package com.jse.ee;

import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import com.jse.Jse;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletResponse;

public class JseServerResponse implements HttpServletResponse {
	
	private HashMap<String,String> headers=new HashMap<String, String>();
	private HashMap<String,Cookie> cookies=new HashMap<>();
	protected final SimpleDateFormat format =
            new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz",Locale.US);
    private OutputStream out;
    private ServletOutputStream outputStream;
    private ByteArrayOutputStream body;
	private int status;//默认OK
	private long contentLength;
	private String msg;
	private PrintWriter writer;
	private Locale local=Locale.getDefault();
	private String characterEncoding;
	private int bufferSize;
	private boolean committed;
	private JseServerRequest request;

    public JseServerResponse(OutputStream out,JseServerRequest request) {
        this.out = out;
        this.body=new ByteArrayOutputStream(1024);
        outputStream=new JseServletOutputStream(body);
		this.writer=new PrintWriter(outputStream,true);
		this.request=request;
    }

	@Override
	public String getCharacterEncoding() {return characterEncoding;}

	@Override
	public String getContentType() {return headers.get("Content-Type");}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {return outputStream;}

	@Override
	public PrintWriter getWriter() throws IOException {return writer;}

	@Override
	public void setCharacterEncoding(String charset) {this.characterEncoding=charset;}

	@Override
	public void setContentLength(int len) {this.contentLength=len;}

	@Override
	public void setContentLengthLong(long len) {this.contentLength=len;}

	@Override
	public void setContentType(String type) {setHeader("Content-Type", type);}

	@Override
	public void setBufferSize(int size) {this.bufferSize=size;}

	@Override
	public int getBufferSize() {return bufferSize;}

	@Override
	public void flushBuffer() throws IOException {
		//动态响应
		if(status == 0){setStatus(200);msg="OK";}
        if (request.getAttribute("$static")==null) {
            out.write(String.format("Http/1.1 %d %s\n", status, msg).getBytes());//头行
            for(Map.Entry<String, String> e : headers.entrySet()){//头域 map集合迭代
                out.write(String.format("%s: %s\n", e.getKey(), e.getValue()).getBytes());
            }
            //cookie迭代
            for (Cookie cookie : cookies.values()){
                String s = cookie.getName()+"="+cookie.getValue();
                if(cookie.getMaxAge()!=0){
                    s += "; max-age=" + cookie.getMaxAge();
                }
                if(cookie.getPath()!=null){
                    s += "; path=" + cookie.getPath();
                }
                out.write(String.format("Set-Cookie: %s\n", s).getBytes());
            }
            //空行
            out.write("\n".getBytes());
            //非响应重定向则输出响应体
            if(status < 300 || status > 399) {
               body.writeTo(out);
               body.flush();
            }
        } else {
        	String type=getContentType();
            out.write(String.format("Http/1.1 %d %s\n", status,msg).getBytes());//头行
            for(Map.Entry<String, String> e : headers.entrySet()){//头域 map集合迭代
                out.write(String.format("%s: %s\n", e.getKey(), e.getValue()).getBytes());
            }
            out.write("\n".getBytes());
            body.writeTo(out);//写入body
        }
		out.flush();
		out.close();
	}

	@Override
	public void resetBuffer() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public boolean isCommitted() {return committed;}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setLocale(Locale loc) {this.local=loc;}

	@Override
	public Locale getLocale() {return local;}

	@Override
	public void addCookie(Cookie cookie) {cookies.put(cookie.getName(), cookie);}
//	//cookie集合转换成字符串
//    public String getCookiesHeader() {
//        if(cookies == null) {
//            return "";
//        }
//
//        String pattern = "EEE, d MMM yyyy HH:mm:ss 'GMT'";
//        SimpleDateFormat sdf = new SimpleDateFormat(pattern, Locale.ENGLISH);
//        StringBuffer str = new StringBuffer();
//        for(Cookie cookie : getCookies()) {
//            str.append("\r\n");
//            str.append("Set-Cookie: ");
//            str.append(cookie.getName() + "=" + cookie.getValue() + "; ");
//            if(cookie.getMaxAge() != -1) {
//                str.append("Expires=");
//                Date now = new Date();
//                Date expire = DateUtil.offset(now, DateField.MINUTE, cookie.getMaxAge());
//                str.append(sdf.format(expire));
//                str.append("; ");
//            }
//            if(cookie.getPath() != null) {
//                str.append("Path=" + cookie.getPath());
//            }
//        }
//        return str.toString();
//    }

	@Override
	public boolean containsHeader(String name) {return headers.containsKey(name);}

	@Override
	public String encodeURL(String url) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String encodeRedirectURL(String url) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void sendError(int sc, String msg) throws IOException {this.status=sc;this.msg=msg;}

	@Override
	public void sendError(int sc) throws IOException {
		this.status=sc;
	}

	@Override
	public void sendRedirect(String location) throws IOException {
		 //设置结果码
        setStatus(301);//Redirect
        //设置跳转页面
        setHeader("Location", location);
	}

	@Override
	public void setDateHeader(String name, long date) {
		headers.putIfAbsent(name,date+"");
	}

	@Override
	public void addDateHeader(String name, long date) {
		headers.put(name,date+"");
	}

	@Override
	public void setHeader(String name, String value) {
		headers.put(name, value);
	}

	@Override
	public void addHeader(String name, String value) {
		headers.putIfAbsent(name, value);
	}

	@Override
	public void setIntHeader(String name, int value) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addIntHeader(String name, int value) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void setStatus(int sc) {this.status=sc;}

	@Override
	public int getStatus() {return status;}

	@Override
	public String getHeader(String name) {return headers.get(name);}

	@Override
	public Collection<String> getHeaders(String name) {return Arrays.asList(headers.get(name).split(" "));}

	@Override
	public Collection<String> getHeaderNames() {return headers.keySet();}
}
